//
//  OAuthController.m
//  SharePad
//
//  Created by junmin liu on 10-10-5.
//  Copyright 2010 Openlab. All rights reserved.
//

#import <QuartzCore/QuartzCore.h>
#import "OAuthController.h"
#import "OAuthEngine.h"
#import "ShareError.h"

@interface OAuthController ()
@property (nonatomic, readonly) UIToolbar *pinCopyPromptBar;

- (NSString *)locateAuthPinInWebView: (UIWebView *) webView;
- (void)showPinCopyPrompt;
- (void)gotPin:(NSString *) pin;
@end


@interface DummyClassForProvidingSetDataDetectorTypesMethod
- (void) setDataDetectorTypes: (int) types;
- (void) setDetectsPhoneNumbers: (BOOL) detects;
@end


@implementation OAuthController
@synthesize delegate = _delegate;
@synthesize navigationBar = _navBar;


- (void) dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver: self];
	_webView.delegate = nil;
	[_webView loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: @""]]];
	[_webView release];
    
    [_navBackgroundImage release];
    [_rightButton release];
	
	self.view = nil;
	[super dealloc];
}

- (id) init {
	if (self = [super init]) {
		_firstLoad = YES;
	}
	return self;
}

#pragma mark View Controller Stuff
- (void) loadView {
	[super loadView];
	_navBar = [[[UINavigationBar alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width, 44)] autorelease];	
	_navBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
	[self.view addSubview: _navBar];
	
	_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 44, 320, 416)];
	_webView.delegate = self;
	_webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	if ([_webView respondsToSelector: @selector(setDetectsPhoneNumbers:)]) {
        [(id) _webView setDetectsPhoneNumbers: NO];   
    }
	if ([_webView respondsToSelector: @selector(setDataDetectorTypes:)]) {
        [(id) _webView setDataDetectorTypes: 0];       
    }	
	[self.view addSubview: _webView];
	
	UINavigationItem *navItem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
	[_navBar pushNavigationItem: navItem animated: NO];
    
    [self setCancelButton:_rightButton];
    [self setNavigationBarBackgroundImage:_navBackgroundImage];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark
#pragma custom decorate interface
-(void)setCancelButton:(UIButton*)button {
    [button retain];
    [_rightButton release];
    _rightButton = button;
    if (_rightButton) {
        [_rightButton addTarget:self action:@selector(cancel:) forControlEvents:UIControlEventTouchUpInside];
        if (_navBar) {
            _navBar.topItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:_rightButton] autorelease];
        }
    } else {
        if (_navBar) {
            _navBar.topItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel:)] autorelease];
        }
    }
}

-(void)setNavigationBarBackgroundImage:(UIImage*)backImage {
    [backImage retain];
    [_navBackgroundImage release];
    _navBackgroundImage = backImage;
    if (_navBar&&[_navBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]) {
        [_navBar setBackgroundImage:backImage forBarMetrics:UIBarMetricsDefault]; 
        } 
}

-(void)setTitleLabel:(UILabel*)label {
    _navBar.topItem.titleView = label;
}

#pragma mark
-(void)starWithReqeust:(NSURLRequest*)request {
    [_webView loadRequest:request];
}

//=============================================================================================================================
#pragma mark Actions
- (void) denied {
	if ([_delegate respondsToSelector: @selector(OAuthControllerFailed:)]) [_delegate OAuthControllerFailed:self error:[ShareError errorWithCode:kShareErrorDenied erorDesc:@"denied"]];
	[self performSelector: @selector(dismissModalViewControllerAnimated:) withObject: (id) kCFBooleanTrue afterDelay: 0.1];
}

- (void) gotPin: (NSString *) pin {    
	if ([_delegate respondsToSelector: @selector(OAuthControllerFinished:pinCode:)]) {
        [_delegate OAuthControllerFinished:self pinCode:pin];        
    }
}

- (void) cancel: (id) sender {
	if ([_delegate respondsToSelector: @selector(OAuthControllerCanceled:)]) [_delegate OAuthControllerCanceled: self];
}

//=============================================================================================================================
#pragma mark Webview Delegate stuff
- (void) webViewDidFinishLoad: (UIWebView *) webView {
	NSString		*authPin = [self locateAuthPinInWebView: webView];	
	if (authPin.length) {
		[self gotPin: authPin];
		return;
	}	
}

- (void) showPinCopyPrompt {
	if (self.pinCopyPromptBar.superview) return;		//already shown
	self.pinCopyPromptBar.center = CGPointMake(self.pinCopyPromptBar.bounds.size.width / 2, self.pinCopyPromptBar.bounds.size.height / 2);
	[self.view insertSubview: self.pinCopyPromptBar belowSubview: self.navigationBar];
	
	[UIView beginAnimations: nil context: nil];
	self.pinCopyPromptBar.center = CGPointMake(self.pinCopyPromptBar.bounds.size.width / 2, self.navigationBar.bounds.size.height + self.pinCopyPromptBar.bounds.size.height / 2);
	[UIView commitAnimations];
}

/*********************************************************************************************************
 I am fully aware that this code is chock full 'o flunk. That said:
 
 - first we check, using standard DOM-diving, for the pin, looking at both the old and new tags for it.
 - if not found, we try a regex for it. This did not work for me (though it did work in test web pages).
 - if STILL not found, we iterate the entire HTML and look for an all-numeric 'word', 7 characters in length
 
 Ugly. I apologize for its inelegance. Bleah.
 
 *********************************************************************************************************/

- (NSString *) locateAuthPinInWebView: (UIWebView *) webView {
    
    NSString *pin;
	
	NSString			*html = [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerText"];

	if (html.length == 0) return nil;
	
	const char			*rawHTML = (const char *) [html UTF8String];
	int					length = strlen(rawHTML), chunkLength = 0;
	int                 chunkPos = -1;
	for (int i = 0; i < length; i++) {
		if (rawHTML[i] < '0' || rawHTML[i] > '9') {
            if (chunkLength >=6) {
                break;
            } else {
                chunkLength = 0;
                chunkPos = -1;
            }
		} else {
			chunkLength++;
            if (chunkPos==-1) {
                chunkPos = i;
            }
        }
	}
    if (chunkLength >=6) {
        char *buffer = (char *) malloc(chunkLength + 1);        
        memmove(buffer, &rawHTML[chunkPos], chunkLength);
        buffer[chunkLength] = 0;        
        pin = [NSString stringWithUTF8String: buffer];
        free(buffer);
        return pin;
    }
	
	return nil;
}

- (UIToolbar *) pinCopyPromptBar {
	if (_pinCopyPromptBar == nil){
		CGRect					bounds = self.view.bounds;
		_pinCopyPromptBar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 44, bounds.size.width, 44)] autorelease];
		_pinCopyPromptBar.barStyle = UIBarStyleBlackTranslucent;
		_pinCopyPromptBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
		
		_pinCopyPromptBar.items = [NSArray arrayWithObjects: 
								   [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace target: nil action: nil] autorelease],
								   [[[UIBarButtonItem alloc] initWithTitle: NSLocalizedString(@"Select and Copy the PIN", @"Select and Copy the PIN") style: UIBarButtonItemStylePlain target: nil action: nil] autorelease], 
								   [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace target: nil action: nil] autorelease], 
								   nil];
	}
	
	return _pinCopyPromptBar;
}

- (void) webViewDidStartLoad: (UIWebView *) webView {
	_loading = YES;
}

- (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *) request navigationType: (UIWebViewNavigationType) navigationType {
	NSData				*data = [request HTTPBody];
	char				*raw = data ? (char *) [data bytes] : "";
	if (raw && strstr(raw, "cancel=")) {
		[self denied];
		return NO;
	}
	return YES;
}

@end
